﻿using SocketTool.Model.BindingModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SocketTool.Com
{
    public class CustomerProtocol
    {
        public CustomerProtocol(IList<CustomerProtocolBindingModel> headProtocol,
         IList<CustomerProtocolBindingModel> tailProtocol,
         bool enable)
        {
            if (headProtocol == null)
                this.HeadList = new List<CustomerProtocolBindingModel>();
            else
                this.HeadList = headProtocol.ToList();

            if (tailProtocol == null)
                this.TailList = new List<CustomerProtocolBindingModel>();
            else
                this.TailList = tailProtocol.ToList();

            this.EnableProtocol = enable;
        }

        public IList<CustomerProtocolBindingModel> HeadList { get; private set; }
        public IList<CustomerProtocolBindingModel> TailList { get; private set; }

        public int ProtocolLen { get => this.HeadList.Count + this.TailList.Count; }

        public bool EnableProtocol { get; private set; }

        /// <summary>
        /// 发送数据协议组装
        /// </summary>
        /// <param name="sourcebt"></param>
        /// <returns></returns>
        public byte[] GetSendData(byte[] sourcebt)
        {
            try
            {
                if (!this.EnableProtocol)
                    return sourcebt;
                List<byte> result = new List<byte>();
                if (HeadList.Count > 0)
                {
                    foreach (var item in this.HeadList)
                    {
                        if (item.IsDtLen)
                            result.AddRange(BitConverter.GetBytes((ushort)sourcebt.Length));
                        else
                            result.Add(item.Byte);
                    }
                }

                result.AddRange(sourcebt);

                if (this.TailList.Count > 0)
                {
                    foreach (var item in this.TailList)
                    {
                        if (item.IsDtLen)
                            result.AddRange(BitConverter.GetBytes((ushort)sourcebt.Length));
                        else
                            result.Add(item.Byte);
                    }
                }
                return result.ToArray();
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"发送数据组装异常 GetSendData {ex.Message}");
                Console.ResetColor();
                return null;
            }
        }

        /// <summary>
        /// 接收的数据转换协议
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="readlength"></param>
        /// <returns></returns>
        public byte[] Parse(ArraySegment<byte> buffer, out int readlength)
        {
            try
            {
                int headLen = this.HeadList.Any(w => w.IsDtLen) ? this.HeadList.Count + 1 : this.HeadList.Count;
                int dtLen = 0;
                int tailLen = this.TailList.Any(w => w.IsDtLen) ? this.TailList.Count + 1 : this.TailList.Count;
                if (!this.EnableProtocol)
                {
                    headLen = 0;
                    dtLen = buffer.Count;
                    tailLen = 0;
                }
                else
                {
                    if (buffer.Count < ProtocolLen)
                    {
                        readlength = buffer.Count;
                        string err = "Error : 接收数据异常，数据格式不符合协议要求！";
                        return Encoding.UTF8.GetBytes(err);
                    }

                    if (this.HeadList.Count > 0)
                    {
                        var headBt = new byte[this.HeadList.Count];
                        Array.Copy(buffer.Array, 0, headBt, 0, this.HeadList.Count);
                        for (int i = 0; i < headBt.Length;)
                        {
                            if (this.HeadList[i].IsDtLen)
                            {
                                //数据长度
                                byte[] bLength = new byte[2];
                                bLength[0] = headBt[i];
                                bLength[1] = headBt[i + 1];
                                dtLen = BitConverter.ToUInt16(bLength, 0);
                                i += 2;
                                continue;
                            }
                            if (headBt[i] != this.HeadList[i].Byte)
                            {
                                readlength = buffer.Count;
                                return Encoding.UTF8.GetBytes($"Error : 接收数据异常，协议头错误，协议位置：{i}！");
                            }
                            i++;
                        }
                    }

                    if (this.TailList.Count > 0)
                    {
                        var tailBt = new byte[this.TailList.Count];
                        Array.Copy(buffer.Array, buffer.Count - tailBt.Length, tailBt, 0, tailBt.Length);
                        for (int i = 0; i < tailBt.Length;)
                        {
                            if (this.TailList[i].IsDtLen)
                            {
                                //数据长度
                                byte[] bLength = new byte[2];
                                bLength[0] = tailBt[i];
                                bLength[1] = tailBt[i + 1];
                                dtLen = BitConverter.ToUInt16(bLength, 0);
                                i += 2;
                                continue;
                            }
                            if (tailBt[i] != this.TailList[i].Byte)
                            {
                                readlength = 0;
                                return Encoding.UTF8.GetBytes($"Error : 接收数据异常，协议尾错误，协议位置：{i}！");
                            }
                            i++;
                        }
                    }

                    if (dtLen < this.ProtocolLen)
                    {
                        readlength = buffer.Count;
                        return Encoding.UTF8.GetBytes("Error : 接收数据异常，数据内容错误！");
                    }

                    if ((this.HeadList.Any(a => a.IsDtLen) || this.TailList.Any(a => a.IsDtLen)) && dtLen == 0)
                    {
                        readlength = this.ProtocolLen;
                        return new byte[0];
                    }

                    if (dtLen == 0)
                        dtLen = buffer.Count;
                }

                var data = new byte[dtLen];
                Buffer.BlockCopy(buffer.Array, headLen, data, 0, dtLen);
                readlength = headLen + dtLen + tailLen;
                return data;
            }
            catch (Exception ex)
            {
                readlength = 0;
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"接收数据转换 Parse {ex.Message}");
                Console.ResetColor();
                return null;
            }
        }
    }
}
